package com.xiaoze.databaseTableControl.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xiaoze.common.utils.DateUtils;
import com.xiaoze.common.utils.SecurityUtils;
import com.xiaoze.common.utils.StringUtils;
import com.xiaoze.common.utils.uuid.UUID;
import com.xiaoze.databaseTableControl.domain.*;
import com.xiaoze.databaseTableControl.service.DataBaseTableService;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.slf4j.XSlf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.sql.*;
import java.util.List;
import java.util.Map;

/**
 * @author 小泽
 * @create 2024-12-11  16:14
 * 记得每天敲代码哦
 */
@Service
@Slf4j
public class DataBaseTableServiceImpl implements DataBaseTableService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Value("${spring.datasource.druid.master.url}")
    private String url;

    @Value("${spring.datasource.druid.master.username}")
    private String username;

    @Value("${spring.datasource.druid.master.password}")
    private String password;

    /**
     * 方法描述: 获取数据库列表
     *
     * @param :
     * @return java.util.List<java.lang.String>
     * @Author 胡昊泽
     * @Date 2024/12/11 16:26
     */
    @Override
    public List<Database> getDatabaseList(DatabaseTable databaseName) {
        String sql = "SELECT " +
                "    s.SCHEMA_NAME, " +
                "    s.DEFAULT_CHARACTER_SET_NAME AS CHARACTER_NAME, " +
                "    s.DEFAULT_COLLATION_NAME AS COLLATION_NAME " +
                "FROM " +
                "    INFORMATION_SCHEMA.SCHEMATA s " +
                "";
        System.out.println(databaseName);
        if (StringUtils.isNotEmpty(databaseName.getSchemaName())) {
            sql += "WHERE " +
                    "    s.SCHEMA_NAME LIKE '%" + databaseName.getSchemaName() + "%'";
        }
        log.info("执行的sql: " + sql);
        return jdbcTemplate.query(sql, (rs, rowNum) -> {
            return new Database().setSchemaName(rs.getString("SCHEMA_NAME"))
                    .setCharacterName(rs.getString("CHARACTER_NAME"))
                    .setCollationName(rs.getString("COLLATION_NAME"));
        });
    }

    /**
     * 方法描述: 根据数据库名称获取该库下面的所有表
     *
     * @param databaseName:
     * @return com.xiaoze.databaseTableControl.domain.TableColumn
     * @Author 胡昊泽
     * @Date 2024/12/11 16:22
     */
    @Override
    public List<Table> getDatabaseTableList(DatabaseTable databaseName) {
        // 定义根据数据库名称查询所有表的sql语句
        String sql = "select table_name,table_comment from information_schema.tables where table_schema = '" + databaseName.getSchemaName() + "'";
        if (StringUtils.isNotEmpty(databaseName.getTableName())) {
            sql += " and table_name like '%" + databaseName.getTableName() + "%'";
        }
        // 开始进行查询
        return jdbcTemplate.query(sql, (rs, rowNum) -> {
            return new Table().setTableName(rs.getString("table_name")).setTableComment(rs.getString("table_comment"));
        });
    }

    /**
     * 方法描述: 根据数据库名称和表名称获取该表下面的所有字段以及解释
     *
     * @param databaseTable
     * @return java.util.List<com.xiaoze.databaseTableControl.domain.TableColumn>
     * @Author 胡昊泽
     * @Date 2024/12/11 17:34
     */
    @Override
    public List<TableColumn> getDatabaseTableColumnList(DatabaseTable databaseTable) {
        // 定义根据数据库名称和表名称查询所有字段的sql语句
        String sql = "SELECT " +
                "c.COLUMN_NAME, " +
                "c.DATA_TYPE, " +
                "CASE " +
                "    WHEN c.DATA_TYPE IN ('char', 'varchar', 'text', 'mediumtext', 'longtext') THEN c.CHARACTER_MAXIMUM_LENGTH " +
                "    ELSE NULL " +
                "END AS 'Max_Length', " +
                "c.IS_NULLABLE, " +
                "c.COLUMN_KEY, " +
                "c.COLUMN_DEFAULT, " +
                "c.EXTRA, " +
                "c.COLUMN_COMMENT, " +
                "CASE " +
                "    WHEN s.INDEX_NAME IS NOT NULL THEN 'Yes' " +
                "    ELSE 'No' " +
                "END AS 'Is_Indexed', " +
                "CASE " +
                "    WHEN c.DATA_TYPE = 'decimal' THEN CONCAT(c.NUMERIC_PRECISION, ', ', c.NUMERIC_SCALE) " +
                "    ELSE NULL " +
                "END AS 'Decimal_Precision_Scale' " +
                "FROM information_schema.COLUMNS c " +
                "LEFT JOIN information_schema.STATISTICS s " +
                "ON " +
                "    c.TABLE_SCHEMA = s.TABLE_SCHEMA " +
                "    AND c.TABLE_NAME = s.TABLE_NAME " +
                "    AND c.COLUMN_NAME = s.COLUMN_NAME " +
                "WHERE " +
                "    c.TABLE_SCHEMA = '" + databaseTable.getSchemaName() + "' " +
                "    AND c.TABLE_NAME = '" + databaseTable.getTableName() + "' " +
                "ORDER BY " +
                "    c.COLUMN_NAME;";
        // 开始进行查询
        return jdbcTemplate.query(sql, (rs, rowNum) -> {
            return new TableColumn()
                    .setColumnName(rs.getString("COLUMN_NAME")) // 字段名
                    .setDataType(rs.getString("DATA_TYPE")) // 数据类型
                    .setMaxLength(rs.getString("Decimal_Precision_Scale") == null ? rs.getString("max_length") : rs.getString("Decimal_Precision_Scale")) // 最大长度
                    .setIsNullable(rs.getString("IS_NULLABLE")) // 是否为空
                    .setColumnKey(rs.getString("COLUMN_KEY")) // 主键
                    .setColumnDefault(rs.getString("COLUMN_DEFAULT")) // 默认值
                    .setExtra(rs.getString("EXTRA")) // 额外信息
                    .setColumnComment(rs.getString("COLUMN_COMMENT")) // 字段注释
                    .setIsIndexed(rs.getString("Is_Indexed")); // 是否索引
        });
    }

    /**
     * 方法描述: 根据数据库名称和表名称获取该表的创建sql语句
     *
     * @param database:
     * @return java.lang.String
     * @Author 胡昊泽
     * @Date 2024/12/13 11:05
     */
    @Override
    public Object getDatabaseTableSql(DatabaseTable database) {
        String sql = "show create table " + "`" + database.getSchemaName() +"`" + "." + database.getTableName();
        log.info("执行的sql: " + sql);
        // 执行sql并返回结果 (此时返回的是两列，需要用map来接收)
        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
        if (!result.isEmpty()) {
            // 提取返回的创建表语句，通常第二列是创建表的 SQL 语句
            return result.get(0).get("Create Table"); // "Create Table"是列名，根据实际情况调整
        }

        return null; // 如果没有结果则返回null
    }

    /**
    * 方法描述: 创建表索引
    * @Author 胡昊泽 
    * @Date 2024/12/16 10:14
      * @param tableIndexAddInput: 
    * @return java.lang.Object
    */ 
    @Override
    public String createTableIndex(TableIndexAddInput tableIndexAddInput) {

        // 最终执行的sql语句
        String sql = "";
        // 获取数据库名称和表名称
        String schemaName = tableIndexAddInput.getSchemaName();
        String tableName = tableIndexAddInput.getTableName();

        // 获取索引类型
        String indexType = tableIndexAddInput.getIndexType(); // 可能是普通索引，唯一索引，聚合索引
        if(indexType.equals("1")){ // 1表示普通索引
            // 定义创建普通索引的sql语句
            sql = "CREATE INDEX " + tableIndexAddInput.getIndexName() + " ON " + "`" + schemaName + "`." + tableName  + " (" + tableIndexAddInput.getIndexColumns() + ") " ;
        }else if(indexType.equals("2")){ // 2表示唯一索引
            // 定义创建唯一索引的sql语句
            sql = "CREATE UNIQUE INDEX " + tableIndexAddInput.getIndexName() + " ON " + "`" + schemaName + "`." + tableName  + " (" + tableIndexAddInput.getIndexColumns() + ") " ;
        }else if(indexType.equals("3")){ // 3表示聚合索引
            // 定义创建聚合索引的sql语句
            sql = "CREATE INDEX " + tableIndexAddInput.getIndexName() + " ON " + "`" + schemaName + "`." + tableName  + " (" + tableIndexAddInput.getIndexColumns() + ") " ;
        }

        // 开始校验sql合法性（为了校验sql合法性，只能采用jdbc的预编译阶段进行校验）
        // 开始校验sql合法性
        // Connection connection = null;
        // try {
        //     // 获取jdbc连接
        //     connection = DriverManager.getConnection(url, username, password);
        //     // String explainSql = "explain " + sql;  // 假设 sql 是你的原始创建索引的 SQL。
        //     log.info("执行的sql: " + sql);
        //
        //     // 预编译sql
        //     PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //
        //     // ResultSet resultSet = preparedStatement.executeQuery();
        //
        //     DatabaseMetaData metaData = connection.getMetaData();
        //     ResultSet columns = metaData.getColumns(null, null,tableIndexAddInput.getTableName() , tableIndexAddInput.getIndexColumns());
        //     if (!columns.next()) {
        //         log.error(columns.toString());
        //         return columns.toString();
        //     }
        //     preparedStatement.close(); // 关闭 preparedStatement
        //
        //     // 在这里可以选择执行一个简单的操作来检查 SQL 的有效性
        //     // 如果 SQL 语法有问题，prepareStatement 会抛出 SQLException
        // } catch (SQLException throwables) {
        //     log.error("SQL 校验失败，请检查 SQL 语法", throwables);
        //     return throwables.getMessage();
        // } finally {
        //     // 关闭数据库连接
        //     if (connection != null) {
        //         try {
        //             connection.close();
        //         } catch (SQLException e) {
        //             log.error("关闭连接失败", e);
        //             return "关闭连接失败";
        //         }
        //     }
        // }

        // 开始进行sql解析
        // 能够执行到这里，证明sql是合法的，将sql记录到sql提交审核表中
        DatabseTableSql databseTableSql = new DatabseTableSql();
        databseTableSql.setBatchId(UUID.getRandom().toString().replace("-", "")); // 批次号
        databseTableSql.setSqlMessage(sql); // sql语句
        databseTableSql.setSubUser("xiaoze"); // 提交人
        databseTableSql.setSubMessage(tableIndexAddInput.getSubMessage()); // 提交说明
        databseTableSql.setExamineStatus("1"); // 审核状态，1-已提交，待审核
        databseTableSql.setCreateTime(DateUtils.getNowDate()); // 提交时间

        return "sql提交审核成功，请等待管理员审核";
    }
}
